package com.jiuyin.dianjing.util;

import android.annotation.SuppressLint;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Base64;

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import static com.jiuyin.dianjing.constant.AppConstant.FILE_PREFIX;
import static com.jiuyin.dianjing.constant.AppConstant.LOG_DELETE_DAYS;
import static com.jiuyin.dianjing.constant.AppConstant.LOG_DIR_NAME;
import static com.jiuyin.dianjing.constant.AppConstant.PROGRAM_APP_ID;

/**
 * 保存日志
 */

public class FileUtil {
    private static final String FILE_LOG_FIRST_NAME = "log_";
    private static final String TEMP_FILE_LOG_FIRST_NAME = "temp_";
    private static final String FILE_EXTENSION_SEPARATOR = ".";
    private static final ThreadLocal<SimpleDateFormat> S_DATE_FORMAT = new ThreadLocal<SimpleDateFormat>() {
        @SuppressLint("SimpleDateFormat")
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd");
        }
    };
    private static final String STORAGE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() +
            File.separator + PROGRAM_APP_ID;

    /**
     * @param message 日志内容
     */
    public static synchronized void saveLogFile(String message) {
        message = stringNowTime() + " " + message + "\n";
        String fileName = getCurLogFileName();
        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state)) {
            String path = getTargetLogFileDirPath();
            String newFileStr = path + File.separator + fileName;
            FileWriter fileWriter = null;
            try {
                if (!isFileExist(newFileStr)) {
                    File newFile = new File(newFileStr);
                    createDir(newFile.getParent());
                    newFile.createNewFile();
                    deleteOldFile(LOG_DELETE_DAYS, path);
                }
                File file = new File(path, fileName);
                fileWriter = new FileWriter(file, true);
                fileWriter.write(message);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                quietClose(fileWriter);
            }
        }
    }

    public static boolean copyFile(String oldPath, String newPath) {
        try {
            if (!isFileExist(newPath)) {
                File newFile = new File(newPath);
                createDir(newFile.getParent());
                newFile.createNewFile();
            }
            File oldFile = new File(oldPath);
            if (!oldFile.exists()) {
                return false;
            } else if (!oldFile.isFile()) {
                return false;
            } else if (!oldFile.canRead()) {
                return false;
            }
            FileInputStream fileInputStream = new FileInputStream(oldPath);
            FileOutputStream fileOutputStream = new FileOutputStream(newPath);
            byte[] buffer = new byte[1024];
            int byteRead;
            while (-1 != (byteRead = fileInputStream.read(buffer))) {
                fileOutputStream.write(buffer, 0, byteRead);
            }
            fileInputStream.close();
            fileOutputStream.flush();
            fileOutputStream.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * @return today log file name
     */
    private static String getCurLogFileName() {
        return FILE_LOG_FIRST_NAME + getNowDate() + FILE_PREFIX;
    }

    public static String getTempCurLogFileName() {
        return TEMP_FILE_LOG_FIRST_NAME + getNowDate() + FILE_PREFIX;
    }

    public static String getTargetLogFileDirPath() {
        return STORAGE_PATH + File.separator + LOG_DIR_NAME;
    }

    /**
     * @return eg: 2018-11-11
     */
    private static String getNowDate() {
        return S_DATE_FORMAT.get().format(new Date());
    }

    private static void quietClose(Closeable closeable) {
        if (null != closeable) {
            try {
                closeable.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private static String stringNowTime() {
        @SuppressLint("SimpleDateFormat")
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return dateFormat.format(new Date());
    }

    private static boolean temporarycreateDir(String path) {
        File dirFile = new File(path);
        return dirFile.exists() || dirFile.mkdirs();
    }

    /**
     * 创建sd上文件夹
     *
     * @param path target dir path
     * @return boolean
     */
    private static boolean createDir(String path) {
        File dirFile = new File(path);
        return dirFile.exists() || dirFile.mkdirs();
    }

    private static boolean isFileExist(String fileName) {
        if (TextUtils.isEmpty(fileName)) {
            return false;
        }
        File file = new File(fileName);
        return file.exists() && file.isFile();
    }

    /**
     * @param path     target dir path
     * @param fileName target file name
     * @return boolean
     */
    private static boolean delFile(String path, String fileName) {
        File file = new File(path, fileName);
        return file.isFile() && file.exists() && file.delete();
    }

    /**
     * @param count delete log file 'count' days ago
     */
    private static void deleteOldFile(int count, String path) {
        File dir = new File(path);
        if (!dir.exists() || !dir.isDirectory() || dir.listFiles() == null) {
            return;
        }
        for (File file : dir.listFiles()) {
            if (!file.isFile()) {
                continue;
            }
            String fileName = getFileNameWithoutExtension(file.getAbsolutePath());
            fileName = fileName.replace(FILE_LOG_FIRST_NAME, "");
            try {
                Date fileDate = S_DATE_FORMAT.get().parse(fileName);
                long diff = System.currentTimeMillis() - fileDate.getTime();
                long diffDays = diff / (24L * 60 * 60 * 1000);
                if (diffDays >= count) {
                    // 删除文件
                    file.delete();
                }
            } catch (ParseException e) {
                e.printStackTrace();
                // 删除文件
                file.delete();
            }
        }
    }


    public static void deleteDirFile(String path) {
        File dir = new File(path);
        if (!dir.exists() || !dir.isDirectory()) {
            return;
        }

        for (File file : dir.listFiles()) {
            if (file.isFile()) {
                // 删除文件
                file.delete();
            } else if (file.isDirectory()) {
                // 递规的方式删除文件夹
                deleteDir(path);
            }
        }
    }

    private static void deleteDir(String path) {
        File dir = new File(path);
        if (!dir.exists() || !dir.isDirectory()) {
            return;
        }

        for (File file : dir.listFiles()) {
            if (file.isFile()) {
                // 删除文件
                file.delete();
            } else if (file.isDirectory()) {
                // 递规的方式删除文件夹
                deleteDir(path);
            }
        }
        dir.delete();// 删除目录本身
    }

    public static String readtxtfile(String strFilePath) {
        //文件内容字符串
        String content = "";
        try {
            FileReader fr = new FileReader(strFilePath);
            BufferedReader r = new BufferedReader(fr);
            content = r.readLine();
        } catch (FileNotFoundException e) {
            LogUtil.log("ReadTxtFile The File doesn't not exist.");
        } catch (IOException e) {
            LogUtil.log("ReadTxtFile : " + e.getMessage());
        }
        return content;
    }

    /**
     * get file name from path, not include suffix
     * <p>
     * <pre>
     *      getFileNameWithoutExtension(null)               =   null
     *      getFileNameWithoutExtension("")                 =   ""
     *      getFileNameWithoutExtension("   ")              =   "   "
     *      getFileNameWithoutExtension("abc")              =   "abc"
     *      getFileNameWithoutExtension("a.mp3")            =   "a"
     *      getFileNameWithoutExtension("a.b.rmvb")         =   "a.b"
     *      getFileNameWithoutExtension("c:\\")              =   ""
     *      getFileNameWithoutExtension("c:\\a")             =   "a"
     *      getFileNameWithoutExtension("c:\\a.b")           =   "a"
     *      getFileNameWithoutExtension("c:a.txt\\a")        =   "a"
     *      getFileNameWithoutExtension("/home/admin")      =   "admin"
     *      getFileNameWithoutExtension("/home/admin/a.txt/b.mp3")  =   "b"
     * </pre>
     *
     * @param filePath string source
     * @return file name from path, not include suffix
     */
    private static String getFileNameWithoutExtension(String filePath) {
        if (TextUtils.isEmpty(filePath)) {
            return filePath;
        }

        int extensionPos = filePath.lastIndexOf(FILE_EXTENSION_SEPARATOR);
        int filePos = filePath.lastIndexOf(File.separator);
        if (filePos == -1) {
            return (extensionPos == -1 ? filePath : filePath.substring(0, extensionPos));
        }
        if (extensionPos == -1) {
            return filePath.substring(filePos + 1);
        }
        return (filePos < extensionPos ? filePath.substring(filePos + 1, extensionPos) : filePath.substring(filePos + 1));
    }

    /**
     * 获取简单文件夹路径
     *
     * @return
     */
    public static final String getLogPath() {
        return PROGRAM_APP_ID + File.separator + LOG_DIR_NAME;
    }

    /**
     * 将图片转换成Base64编码的字符串
     *
     * @param path
     * @return base64编码的字符串
     */
    public static String imageToBase64(String path) {
        if (TextUtils.isEmpty(path)) {
            return null;
        }
        InputStream is = null;
        byte[] data = null;
        String result = null;
        try {
            is = new FileInputStream(path);
            data = new byte[is.available()];
            is.read(data);
            result = Base64.encodeToString(data, Base64.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != is) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
        return result;
    }

    /**
     * base64编码字符集转化成图片文件。
     *
     * @param base64Str
     * @param path      文件存储路径
     * @return 是否成功
     */
    public static boolean base64ToFile(String base64Str, String path) {
        byte[] data = Base64.decode(base64Str, Base64.DEFAULT);
        for (int i = 0; i < data.length; i++) {
            if (data[i] < 0) {
                data[i] += 256;
            }
        }
        OutputStream os = null;
        try {
            os = new FileOutputStream(path);
            os.write(data);
            os.flush();
            os.close();
            return true;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            if (null != os) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
